package com.aimusic.service.impl;

import com.aimusic.client.RedisClient;
import com.aimusic.domain.dto.LoginRequestDTO;
import com.aimusic.domain.dto.RegisterDTO;
import com.aimusic.domain.dto.UserInfoResponseDTO;
import com.aimusic.domain.po.User;
import com.aimusic.domain.po.UserProfile;
import com.aimusic.domain.vo.LoginResponseVO;
import com.aimusic.enums.PhoneCode;
import com.aimusic.mapper.UserMapper;
import com.aimusic.service.IUserProfileService;
import com.aimusic.service.IUserService;
import com.aimusic.utils.JwtUtils;
import com.aimusic.utils.PasswordEncoderUtil;
import com.aimusic.utils.VerifyCodeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户表（手机号登录核心表） 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-09-25
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private final PasswordEncoderUtil passwordEncoderUtil;
    private final JwtUtils jwtUtils;
    private final VerifyCodeUtil verifyCodeUtil;
    private final RedisClient redisClient;
    private final IUserProfileService userProfileService;


    @Override
    public LoginResponseVO login(LoginRequestDTO loginRequestDTO) {
        //密码加密
        String encode = passwordEncoderUtil.encode(loginRequestDTO.getPassword());
        log.info("密码加密成功：{}", encode);
        //根据手机号和密码查询user表
        User user = this.getOne(new QueryWrapper<User>().eq("phone", loginRequestDTO.getPhone()));
        if(user != null){
            if (!passwordEncoderUtil.matches(loginRequestDTO.getPassword(), encode)) {
                return null;
            }
            log.info("登录成功，用户信息：{}", user);
            Map<String, Object> claims = new HashMap<>();
            claims.put("id", user.getId()); // 必须：用户唯一标识（TokenFilter依赖）
            claims.put("phone", user.getPhone()); // 推荐：辅助验证和日志定位
            claims.put("status", user.getStatus()); // 推荐：快速判断账号状态
            String jwt = jwtUtils.generateJwt(claims);
            log.info("生成JWT成功：{}", jwt);
            //封装成VO返回
            UserInfoResponseDTO userInfoResponseDTO=new UserInfoResponseDTO();
            userInfoResponseDTO.setMaskedPhone(UserInfoResponseDTO.maskPhone(user.getPhone()));
            userInfoResponseDTO.setUserId(user.getId().intValue());
            userInfoResponseDTO.setName(user.getUsername());
            userInfoResponseDTO.setAvatar(user.getPassword());
            LoginResponseVO loginResponseVO = new LoginResponseVO(jwt, userInfoResponseDTO);
            return loginResponseVO;
        }
        return null;
    }

    /**
     * 发送短信验证码,并存入Redis
     *
     * @param loginRequestDTO
     * @param i
     */
    @Override
    public void sendSms(LoginRequestDTO loginRequestDTO, int i) {
        String code = verifyCodeUtil.generateNumericCode(6);
        log.info("生成验证码成功：{}", code);
        if(i == 1){
            //验证码存入redis
            redisClient.setKey(PhoneCode.REGISTER.getKey(loginRequestDTO.getPhone()), code, PhoneCode.REGISTER.getExpire(), PhoneCode.REGISTER.getTimeUnit());

        }else if(i == 2){
            //验证码存入redis
            redisClient.setKey(PhoneCode.FORGET_PASSWORD.getKey(loginRequestDTO.getPhone()), code, PhoneCode.FORGET_PASSWORD.getExpire(), PhoneCode.FORGET_PASSWORD.getTimeUnit());
        }
    }

    @Override
    @Transactional
    public void register(RegisterDTO registerDTO) {
        //验证码校验
        String verifyCode = redisClient.getKey(PhoneCode.REGISTER.getKey(registerDTO.getPhone()));
        if (!verifyCode.equals(registerDTO.getVerifyCode())) {
            throw new RuntimeException("验证码错误");
        }

        //查询手机号是否已经注册
        User user = this.getOne(new QueryWrapper<User>().eq("phone", registerDTO.getPhone()));
        if (user != null) {
            throw new RuntimeException("手机号已注册");
        }

        //密码加密，存储到数据库
        String encode = passwordEncoderUtil.encode(registerDTO.getPassword());
        user = new User();
        user.setPhone(registerDTO.getPhone());
        user.setPassword(encode);
        user.setStatus(1);
        this.save(user);

        // 向user_profile表插入数据
        UserProfile userProfile = new UserProfile();
        userProfile.setUserId(user.getId());
        // 设置头像(默认头像)
        userProfile.setAvatar("https://picsum.photos/200/300");
        // 设置昵称,取手机号后6位
        userProfile.setNickname("用户" + user.getPhone().substring(user.getPhone().length() - 6));
        userProfileService.save(userProfile);

        log.info("用户注册成功：{}", user);

    }

    @Override
    public void forgetPassword(RegisterDTO registerDTO) {
        //验证码校验
        String verifyCode = redisClient.getKey(PhoneCode.FORGET_PASSWORD.getKey(registerDTO.getPhone()));
        if (!verifyCode.equals(registerDTO.getVerifyCode())) {
            throw new RuntimeException("验证码错误");
        }

        //查询数据库中是否有相关手机信息
        User user = this.getOne(new QueryWrapper<User>().eq("phone", registerDTO.getPhone()));
        if (user == null) {
            throw new RuntimeException("手机号未注册");
        }

        //密码加密，更新数据库中的密码
        String encode = passwordEncoderUtil.encode(registerDTO.getPassword());
        user.setPassword(encode);
        this.update(
                Wrappers.<User>lambdaUpdate()
                        .set(User::getPassword, encode)
                        .eq(User::getPhone, registerDTO.getPhone())
        );
        log.info("用户重置密码成功：{}", user);

    }
}
